/**
 * 
 */
package cn.ad.server.web.spring.service.actions;

import cn.ad.server.common.utils.BrowserUtils;
import cn.ad.server.common.utils.IPUtils;
import cn.ad.server.persistence.*;
import cn.ad.server.web.servlet.v2.requests.*;
import cn.ad.server.web.spring.service.actions.command.ClickAndImpressionCommand;
import cn.ad.server.web.spring.service.actions.context.IPContext;
import cn.ad.server.web.spring.service.actions.presentation.ClickPresentation;
import cn.ad.server.biz.internal.AdService;
import cn.ad.server.domain.IPDetail;
import cn.ad.server.domain.ad.*;
import cn.ad.server.domain.enumration.ChargeType;
import cn.ad.server.domain.enumration.FeeType;
import cn.ad.server.domain.enumration.ResponseStatusCode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author Wu Chengjun
 *
 */

@Component("action-tracking")
public class AdTrackingAction implements ITrackingAction {

	static Logger logger = LoggerFactory.getLogger(AdTrackingAction.class);

	@Autowired
	private AdSpaceRepository adSpaceRepository;

	@Autowired
	private CreativeRepository creativeRepository;

	@Autowired
	private StrategyRepository strategyRepository;

	@Autowired
	private ConfigRepository configRepository;

	@Autowired
	private AdTemplateRepository adTemplateRepository;

	@Autowired
	private PlatformRepository platformRepository;

	@Autowired
	private CampaignRepository campaignRepository;

	@Autowired
	private TagRepository tagRepository;

	@Autowired
	private DeviceRepository deviceRepository;

	@Autowired
	private AdService adService;
	
	@Autowired
	private GuidRepository guidRepository;
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * cn.falconnect.adserver.adapter.ITrackingAction
	 * #handle(cn.ad.server.web.servlet.v2.requests.
	 * TrackingRequest)
	 */
	@Override
	public TrackingResponse handle(TrackingRequest request) {
		TrackingResponse response = null;
		try {
			if (request instanceof ImpressionRequest) {
				response = new ImpressionResponse();
				handle(request, response);
			} else if (request instanceof ClickRequest) {
				response = new ClickResponse();
				recordDeviceId(request);
				handle(request, response);
			} else if (request instanceof WinoticeRequest) {
				WinoticeResponse res = new WinoticeResponse();
				response = res;
				handleWinotice((WinoticeRequest) request, res);
			}
		} finally {
			adService.unbond();
		}
		return response;
	}

	/**
	 * 处理winotice请求
	 * 
	 * @param req
	 * @param res
	 */
	private void handleWinotice(WinoticeRequest req, WinoticeResponse res) {
		GuidValueObject guidVo = getGuidData(req.getGuid());
		Strategy strategy = strategyRepository.findById(Integer.valueOf(req.getSid()));
		if (guidVo == null) {
			res.setStatus(ResponseStatusCode.RES_NOTFOUND_GUID.getValue());
		} else {
			writeResponseFromGuid(guidVo, res);
		}
		if (strategy == null) {
			res.setStatus(ResponseStatusCode.INVALID_STRATEGY.getValue());
		} else {
			if (strategy.getCampaign() == null) {
				throw new NullPointerException(
						"处理win notice请求时异常, 从策略实例[id:" + strategy.getId() + "]中获取的订单实例为null。  : ");
			} else {
				res.setCampaignId(strategy.getCampaign().getId());
			}
			chargeWinotice(req, res);
		}
	}

	/**
	 * 处理监测业务请求
	 */
	private void handle(TrackingRequest req, TrackingResponse res) {
		GuidValueObject guidVo = getGuidData(req.getGuid());
		Strategy s = null;
		AdSpace adSpace = null;
		if (guidVo == null) {
			res.setStatus(ResponseStatusCode.RES_NOTFOUND_GUID.getValue());
			return;
		}
		if (guidVo.getSerializeVersion() == 2) {
			handle(req, res, guidVo);
		} else {
			s = strategyRepository.findById(Integer.valueOf(req.getSid()));
			adSpace = adSpaceRepository.findAdSpaceById(req.getAid());
			handle(req, res, guidVo, adSpace, s);
		}
		if (res.getStatus() == ResponseStatusCode.SUCCESS.getValue()) {
			if (res instanceof ClickResponse) {
				if (validClick(guidVo, (ClickResponse) res, Integer.valueOf(req.getChannelID()))) {
					if (guidVo.getSerializeVersion() == 2) {
						clickCount(guidVo);
					} else {
						clickCount(s);
					}
				}
			} else if (res instanceof ImpressionResponse) {
				if (validImpression(guidVo, (ImpressionResponse) res, Integer.valueOf(req.getChannelID()))) {
					if (guidVo.getSerializeVersion() == 2) {
						impressionsCount(guidVo);
					} else {
						impressionsCount(s);
					}
				}
			}
		}

	}

	/**
	 * 处理监测请求
	 * 
	 * @param req
	 * @param res
	 * @param guidVO
	 * @param adSpace
	 * @param strategy
	 */
	@Deprecated
	private void handle(TrackingRequest req, TrackingResponse res, GuidValueObject guidVO, AdSpace adSpace,
			Strategy strategy) {
		if (guidVO == null) {
			res.setStatus(ResponseStatusCode.RES_NOTFOUND_GUID.getValue());
		} else {
			writeResponseFromGuid(guidVO, res);
		}
		if (strategy == null) {
			res.setStatus(ResponseStatusCode.INVALID_STRATEGY.getValue());
		} else {
			if (strategy.getCampaign() != null)
				res.setCampaignId(strategy.getCampaign().getId());
			chargeTracking(req, res, strategy, adSpace);
		}
	}

	private void handle(TrackingRequest req, TrackingResponse res, GuidValueObject guidVO) {
		if (guidVO == null) {
			res.setStatus(ResponseStatusCode.RES_NOTFOUND_GUID.getValue());
		} else {
			writeResponseFromGuid(guidVO, res);
		}

		if (guidVO.getStrategyVO() == null) {
			res.setStatus(ResponseStatusCode.INVALID_STRATEGY.getValue());
		} else {
			if (guidVO.getCampaignVO() != null)
				res.setCampaignId(guidVO.getCampaignVO().getId());
			chargeTracking(req, res, guidVO);
		}
	}

	/**
	 * 验证点击是否有效
	 * 
	 * @param guidVO
	 * @param res
	 * @return 有效返回true, 否则返回false
	 */
	private boolean validClick(GuidValueObject guidVO, ClickResponse res, int channelId) {
		if (!countAndValidClickOnGuid(guidVO, channelId)) {
			res.setStatus(ResponseStatusCode.CLICK_OVER_LIMIT_OF_GUID.getValue());
			return false;
		} else if (!countAndValidClickOnUserCreative(guidVO)) {
			res.setStatus(ResponseStatusCode.CLICK_OVER_LIMIT_OF_USERACREATIVE.getValue());
			return false;
		} else {
			return true;
		}
	}

	/**
	 * 验证展示请求的有效性
	 * 
	 * @param guidVO
	 * @param res
	 * @return 有效返回ture 无效返回false
	 */
	private boolean validImpression(GuidValueObject guidVO, ImpressionResponse res, int channelId) {
		if (!countAndValidImpressionOnGUID(guidVO, channelId)) {
			res.setStatus(ResponseStatusCode.IMPRESSION_OVER_LIMIT_OF_GUID.getValue());
			return false;
		} else if (!countAndValidImpressionOnUserCreative(guidVO)) {
			res.setStatus(ResponseStatusCode.IMPRESSION_OVER_LIMIT_OF_USERACREATIVE.getValue());
			return false;
		} else {
			return true;
		}
	}

	/**
	 * 计数并验证点击有效性，在同一个guid上
	 * 
	 * @param guidVO
	 * @return 有效返回true;
	 */
	private boolean countAndValidClickOnGuid(GuidValueObject guidVO, int channelId) {
//		long guidCountValue = adSpaceRepository.countGuidClick(guidVO, channelId);
		long guidCountValue = guidRepository.countGuidClick(guidVO, channelId);
		int guidClickLimit = this.configRepository.fetchGuidClickLimit();
		return guidCountValue <= guidClickLimit;
	}

	/**
	 * 计数验证点击有效性， 在用户和创意的上的限制
	 * 
	 * @param guidVO
	 * @return 有效返回true 无效返回false
	 */
	private boolean countAndValidClickOnUserCreative(GuidValueObject guidVO) {
		long userAndCreativeCountValue = creativeRepository.countUserAndCreativeClick(guidVO.getCid(),
				guidVO.getMuniqueId());
		int userAndCreativeClickLimit = this.configRepository.fetchUserAndCreativeClickLimit();
		return userAndCreativeCountValue <= userAndCreativeClickLimit;
	}

	/**
	 * 计数并验证展示有效性，在同一个guid上
	 * 
	 * @param guidVO
	 * @return 有效返回true 无效返回false
	 */
	private boolean countAndValidImpressionOnGUID(GuidValueObject guidVO, int channelId) {
//		long guidCountValue = adSpaceRepository.countGuidImpressions(guidVO, channelId);
		long guidCountValue = guidRepository.countGuidImpressions(guidVO, channelId);
		int guidImpressionsLimit = this.configRepository.fetchGuidImpressionsLimit();
		return guidCountValue <= guidImpressionsLimit;

	}

	/**
	 * 计数并验证展示有效性-- 在用户和创意上
	 * 
	 * @param guidVO
	 * @return 有效返回true 无效返回false
	 */
	private boolean countAndValidImpressionOnUserCreative(GuidValueObject guidVO) {
		long userAndCreativeCountValue = creativeRepository.countUserAndCreativeImpressions(guidVO.getCid(),
				guidVO.getMuniqueId());
		int userAndCreativeImpressionsLimit = this.configRepository.fetchUserAndCreativeImpressionsLimit();
		return userAndCreativeCountValue <= userAndCreativeImpressionsLimit;
		// cp.setExceptionType(ExceptionType.E5.getValue());
	}

	/**
	 * 根据guid获取GuidValueObject
	 * 
	 * @param guid
	 * @return
	 */
	private GuidValueObject getGuidData(String guid) {
		if (StringUtils.isNotEmpty(guid)) {
			return guidRepository.findGuidVo(guid);
		}
		return null;
	}

	private void chargeTracking(TrackingRequest request, TrackingResponse response, GuidValueObject guidVO) {
		if (response instanceof ImpressionResponse) {
			if (guidVO.getStrategyVO() != null) {
				if (guidVO.getStrategyVO().getFeeType() == FeeType.CPM.getValue()) {
					response.setIncome(guidVO.getStrategyVO().getUnitPrice() * 0.001);
				}
			}
			if (guidVO.getAdSpaceVO() != null) {
				if (guidVO.getAdSpaceVO().getChargeType() == ChargeType.CPM.getValue()) {
					response.setPayment(guidVO.getAdSpaceVO().getChargePrice() * 0.001);
				}
			}
		} else if (response instanceof ClickResponse) {
			if (guidVO.getStrategyVO() != null) {
				if (guidVO.getStrategyVO().getFeeType() == FeeType.CPC.getValue()) {
					response.setIncome(guidVO.getStrategyVO().getUnitPrice());
				}
			}
			if (guidVO.getAdSpaceVO() != null) {
				if (guidVO.getAdSpaceVO().getChargeType() == ChargeType.CPC.getValue()) {
					response.setPayment(guidVO.getAdSpaceVO().getChargePrice());
				}
			}
		}
	}

	/**
	 * 根据策略以及广告为本次监测计费
	 * 
	 * @param response
	 * @param strategy
	 * @param adspace
	 */
	// @Deprecated
	// private void chargeTracking(TrackingRequest request, TrackingResponse
	// response, Strategy strategy,
	// AdSpace adspace) {
	// if (response instanceof ImpressionResponse) {
	//
	// if (strategy.getFeeType() == FeeType.CPM.getValue()) {
	// response.setIncome(strategy.getUnitPrice().doubleValue() * 0.001);
	// }
	// if (adspace != null) {
	// if (adspace.getChargeType() == ChargeType.CPM.getValue()) {
	// response.setPayment(adspace.getChargePrice().doubleValue() * 0.001);
	// }
	// }
	// } else if (response instanceof ClickResponse) {
	// if (strategy.getFeeType() == FeeType.CPC.getValue()) {
	// response.setIncome(strategy.getUnitPrice().doubleValue());
	// }
	//
	// if (adspace != null) {
	// if (adspace.getChargeType() == ChargeType.CPC.getValue()) {
	// response.setPayment(adspace.getChargePrice().doubleValue());
	// }
	// }
	// }
	// }

	@Deprecated
	private void chargeTracking(TrackingRequest request, TrackingResponse response, Strategy strategy,
			AdSpace adspace) {
		if (response instanceof ImpressionResponse) {
			if (strategy.getFeeType() == FeeType.CPM.getValue()) {
				response.setIncome(strategy.getUnitPrice().doubleValue() * 0.001);
			}
			if (adspace != null) {
				if (adspace.getChargeType() == ChargeType.CPM.getValue()) {
					response.setPayment(adspace.getChargePrice().doubleValue() * 0.001);
				}
			}
		} else if (response instanceof ClickResponse) {
			// logger.info("click");
			if (strategy.getFeeType() == FeeType.CPC.getValue()) {
				response.setIncome(strategy.getUnitPrice().doubleValue());
				// logger.info("income : {}",
				// strategy.getUnitPrice().doubleValue());
			}

			if (adspace != null) {
				if (adspace.getChargeType() == ChargeType.CPC.getValue()) {
					response.setPayment(adspace.getChargePrice().doubleValue());
					// logger.info("payment : {}",
					// adspace.getChargePrice().doubleValue());
				}
			}
			// logger.info("-----res {}----",response);
		}
	}

	/**
	 * 计费winotice
	 * 
	 * @param request
	 * @param response
	 */
	private void chargeWinotice(WinoticeRequest request, WinoticeResponse response) {
		response.setPayment(((WinoticeRequest) request).getWin_price());
	}

	/**
	 * 根据guid设置响应结果
	 * 
	 * @param response
	 */
	private void writeResponseFromGuid(GuidValueObject guidVo, TrackingResponse response) {
		if (response == null || guidVo == null) {
			throw new NullPointerException("TrackingResponse or guidVo is null");
		}

		response.setAdFormat(guidVo.getFid());
		response.setTemplateId(guidVo.getTemplateId());

		response.setAdspaceId(guidVo.getAid());
		response.setMuniqueType(String.valueOf(guidVo.getMuniqueType()));
		response.setMuniqueId(guidVo.getMuniqueId());
		response.setMobOps(String.valueOf(guidVo.getOperator()));
		response.setBrand(guidVo.getBrand());
		response.setModel(guidVo.getPlatform());
		response.setOs(String.valueOf(guidVo.getOs()));
		response.setConnType(guidVo.getNetwork());
		response.setDeviceType(guidVo.getDeviceType());
		response.setLatitude(String.valueOf(guidVo.getLatitude()));
		response.setLongitude(String.valueOf(guidVo.getLongitude()));
		response.setIp(guidVo.getIp());
		response.setStrategyId(guidVo.getSid());
		response.setCreativeId(guidVo.getCid());
		response.setMaterialId(guidVo.getMid());

		if (!StringUtils.isEmpty(guidVo.getDeviceSize()) && guidVo.getDeviceSize().contains("*")) {
			String[] d = guidVo.getDeviceSize().split("\\*");
			response.setScreenWidth(Integer.valueOf(d[0]));
			response.setScreenHeight(Integer.valueOf(d[1]));
		}
		AdMaterial adMaterial = this.creativeRepository.findAdMaterialById(guidVo.getMid());
		if (adMaterial != null) {
			response.setCreativeHeight(adMaterial.getAdSize().getHeight());
			response.setCreativeWidth(adMaterial.getAdSize().getWidth());
		}

		response.setMac(guidVo.getMac());
		response.setMac1(guidVo.getMac1());
		response.setImei(guidVo.getImei());
		response.setAnid(guidVo.getAnid());
		response.setAaid(guidVo.getAaid());
		response.setIdfa(guidVo.getIdfa());
		response.setUdid(guidVo.getUdid());
		response.setDuid(guidVo.getDuid());

		response.setImeisha1(guidVo.getImeisha1());
		response.setDpidsha1(guidVo.getDpidsha1());
		response.setMacsha1(guidVo.getMacsha1());
		response.setImeimd5(guidVo.getImeimd5());
		response.setDpidmd5(guidVo.getDpidmd5());
		response.setMacmd5(guidVo.getMacmd5());
		response.setCustomId(guidVo.getCustomId());
		response.setOpenUdid(guidVo.getOpenUdid());
	}

	@Deprecated
	public void handleClick(ClickAndImpressionCommand aCommand, ClickPresentation cp) {
		cp.setRequestTimestamp(System.currentTimeMillis());
		cp.setRequestIp(aCommand.getIp());
		cp.setServerId(IPUtils.getHostName());
		cp.setPlatformId(aCommand.getPlatform_id());
		cp.setAdxType(StringUtils.isBlank(aCommand.getPlatform_id()) ? 1 : Integer.valueOf(aCommand.getPlatform_id()));

		GuidValueObject guidVo = null;
		if (StringUtils.isNotEmpty(aCommand.getGuid())) {
			guidVo = guidRepository.findGuidVo(aCommand.getGuid());
		}

		AdSpace adSpace = null;
		if (StringUtils.isNoneEmpty(aCommand.getAid()) && !"0".equals(aCommand.getAid())) {
			adSpace = this.adSpaceRepository.findAdSpaceById(Long.valueOf(aCommand.getAid()));

			if (adSpace == null) {
				logger.error("adSapce is null : {}", aCommand.toString());
			}

			if (adSpace.getAdFormat() != null)
				cp.setAdFormat(adSpace.getAdFormat().getValue());

			AdTemplate adTemplate = adSpace.getAdTemplate();
			if (adTemplate != null) {
				cp.setTemplateId(adSpace.getAdTemplate().getId());
			}
		}

		if (aCommand.isImp()) {
			cp.setEventType(2);
		} else {
			cp.setEventType(3);
		}

		cp.setGuid(aCommand.getGuid());
		cp.setExceptionType(0);
		cp.setUa(aCommand.getUa());
		cp.setBrowser(BrowserUtils.getBrowser(aCommand.getUa()));

		if (guidVo != null) {
			if (adSpace == null) {
				cp.setAdFormat(guidVo.getFid());
				cp.setTemplateId(guidVo.getTemplateId());
			}

			IPDetail ipDetail = IPContext.instance().getIPDetail(IPUtils.convertIPToLong(guidVo.getIp()));
			if (ipDetail != null) {
				cp.setCountryId(ipDetail.getCountryId());
				cp.setStateId(ipDetail.getStateId());
				cp.setCityId(ipDetail.getCityId());
				cp.setAreaId(ipDetail.getDistrictId());
			}

			cp.setAdspaceId(guidVo.getAid());
			cp.setMuniqueType(String.valueOf(guidVo.getMuniqueType()));
			cp.setMuniqueId(guidVo.getMuniqueId());
			cp.setMobOps(String.valueOf(guidVo.getOperator()));
			cp.setBrand(guidVo.getBrand());
			cp.setModel(guidVo.getPlatform());
			cp.setOs(String.valueOf(guidVo.getOs()));
			cp.setConnType(guidVo.getNetwork());
			cp.setDeviceType(guidVo.getDeviceType());
			cp.setLatitude(String.valueOf(guidVo.getLatitude()));
			cp.setLongitude(String.valueOf(guidVo.getLongitude()));
			cp.setIp(guidVo.getIp());
			cp.setStrategyId(guidVo.getSid());

			cp.setCreativeId(guidVo.getCid());
			cp.setMaterialId(guidVo.getMid());

			if (!StringUtils.isEmpty(guidVo.getDeviceSize()) && guidVo.getDeviceSize().contains("*")) {
				String[] d = guidVo.getDeviceSize().split("\\*");
				cp.setScreenWidth(Integer.valueOf(d[0]));
				cp.setScreenHeight(Integer.valueOf(d[1]));
			}
			AdMaterial adMaterial = this.creativeRepository.findAdMaterialById(guidVo.getMid());
			if (adMaterial != null) {
				cp.setCreativeHeight(adMaterial.getAdSize().getHeight());
				cp.setCreativeWidth(adMaterial.getAdSize().getWidth());
			}

			cp.setMac(guidVo.getMac());
			cp.setMac1(guidVo.getMac1());
			cp.setImei(guidVo.getImei());
			cp.setAnid(guidVo.getAnid());
			cp.setAaid(guidVo.getAaid());
			cp.setIdfa(guidVo.getIdfa());
			cp.setUdid(guidVo.getUdid());
			cp.setDuid(guidVo.getDuid());

			cp.setImeisha1(guidVo.getImeisha1());
			cp.setDpidsha1(guidVo.getDpidsha1());
			cp.setMacsha1(guidVo.getMacsha1());
			cp.setImeimd5(guidVo.getImeimd5());
			cp.setDpidmd5(guidVo.getDpidmd5());
			cp.setMacmd5(guidVo.getMacmd5());
			cp.setCustomId(guidVo.getCustomId());
			cp.setOpenUdid(guidVo.getOpenUdid());

		} else {
			cp.setExceptionType(ResponseStatusCode.RES_NOTFOUND_GUID.getValue());

			if (StringUtils.isNoneEmpty(aCommand.getAid())) {
				cp.setAdspaceId(Long.valueOf(aCommand.getAid()));
				if ("3".equals(aCommand.getHandleType())) {
					// 转发成功
					cp.setEventType(5);
				}
			}

			if (StringUtils.isNotEmpty(aCommand.getSid())) {
				cp.setStrategyId(Long.parseLong(aCommand.getSid()));
			}

			if (StringUtils.isNotEmpty(aCommand.getCid())) {
				cp.setCreativeId(Long.parseLong(aCommand.getCid()));
			}

			if (StringUtils.isNotEmpty(aCommand.getMid())) {
				cp.setMaterialId(Long.parseLong(aCommand.getMid()));
			}
		}

		long sid = StringUtils.isBlank(aCommand.getSid()) ? 0 : Integer.valueOf(aCommand.getSid());
		if (sid == 0 && guidVo != null) {
			sid = guidVo.getSid();
		}

		Strategy s = strategyRepository.findById(sid);

		if (s != null) {
			if (s.getCampaign() != null)
				cp.setCampaignId(s.getCampaign().getId());
			if (aCommand.isImp()) {
				if (s.getFeeType() == FeeType.CPM.getValue()) {
					cp.setIncome(s.getUnitPrice().doubleValue() / 1000);
				}

				if (adSpace != null) {
					if (adSpace.getChargeType() == ChargeType.CPM.getValue()) {
						cp.setPayment(adSpace.getChargePrice().doubleValue() / 1000);
					}
				}
			} else {
				if (s.getFeeType() == FeeType.CPC.getValue()) {
					cp.setIncome(s.getUnitPrice().doubleValue());
				}
			}
		} else {
			if (adSpace != null) {
				if (adSpace.getChargeType() == ChargeType.CPC.getValue()) {
					cp.setPayment(adSpace.getChargePrice().doubleValue());
				}
			}
			if ("3".equals(aCommand.getHandleType())) {
				// 转发成功
				cp.setExceptionType(ResponseStatusCode.SUCCESS.getValue());
			} else {
				cp.setExceptionType(ResponseStatusCode.INVALID_STRATEGY.getValue());
			}
		}

		if (guidVo != null) {
			// 作弊的计数并检查是否作弊？不是作弊的请求，才走入正常的控量计数流程
			if ("1".equals(aCommand.getHandleType())
					&& !checkAndCountClickCheat(guidVo, cp, Integer.valueOf(aCommand.getPlatform_id()))) {
				clickCount(s);
			} else if ("2".equals(aCommand.getHandleType())
					&& !checkAndCountImpressionsCheat(guidVo, cp, Integer.valueOf(aCommand.getPlatform_id()))) {
				impressionsCount(s);
			}
		}
	}

	public void clickCount(GuidValueObject guidVO) {
		this.strategyRepository.countClick(guidVO);
	}

	public void impressionsCount(GuidValueObject guidVO) {
		this.strategyRepository.countImpressions(guidVO);
	}

	@Deprecated
	public void clickCount(Strategy s) {
		this.strategyRepository.countClick(s);
	}

	@Deprecated
	public void impressionsCount(Strategy s) {
		this.strategyRepository.countImpressions(s);
	}

	/**
	 * 检查是否作弊，通过以下两个维度： 1.通过guid的计数 2.通过用户设备号和创意的计数 只要其一超过配置的阀值，就算作弊
	 * 
	 * @return
	 */
	@Deprecated
	public boolean checkAndCountClickCheat(GuidValueObject guidVO, ClickPresentation cp, int channelId) {
//		long guidCountValue = adSpaceRepository.countGuidClick(guidVO, channelId);
		long guidCountValue = guidRepository.countGuidClick(guidVO, channelId);
		
		int guidClickLimit = this.configRepository.fetchGuidClickLimit();
		if (guidCountValue > guidClickLimit) {
			cp.setExceptionType(ResponseStatusCode.CLICK_OVER_LIMIT_OF_GUID.getValue());
			return true;
		}

		long userAndCreativeCountValue = creativeRepository.countUserAndCreativeClick(guidVO.getCid(),
				guidVO.getMuniqueId());
		int userAndCreativeClickLimit = this.configRepository.fetchUserAndCreativeClickLimit();
		if (userAndCreativeCountValue > userAndCreativeClickLimit) {
			cp.setExceptionType(ResponseStatusCode.CLICK_OVER_LIMIT_OF_USERACREATIVE.getValue());
			return true;
		}
		return false;
	}

	@Deprecated
	public boolean checkAndCountImpressionsCheat(GuidValueObject guidVO, ClickPresentation cp, int channelId) {
//		long guidCountValue = adSpaceRepository.countGuidImpressions(guidVO, channelId);
		long guidCountValue = guidRepository.countGuidImpressions(guidVO, channelId);
		int guidImpressionsLimit = this.configRepository.fetchGuidImpressionsLimit();
		if (guidCountValue > guidImpressionsLimit) {
			cp.setExceptionType(ResponseStatusCode.IMPRESSION_OVER_LIMIT_OF_GUID.getValue());
			return true;
		}

		long userAndCreativeCountValue = creativeRepository.countUserAndCreativeImpressions(guidVO.getCid(),
				guidVO.getMuniqueId());
		int userAndCreativeImpressionsLimit = this.configRepository.fetchUserAndCreativeImpressionsLimit();
		if (userAndCreativeCountValue > userAndCreativeImpressionsLimit) {
			cp.setExceptionType(ResponseStatusCode.IMPRESSION_OVER_LIMIT_OF_USERACREATIVE.getValue());
			return true;
		}
		return false;
	}

	/**
	 * record deviceid
	 * 
	 * @param s
	 */
	public void recordDeviceId(TrackingRequest req) {
		String ch = req.getCh();
		if (StringUtils.isEmpty(ch)) {
			return;
		}
		String uniqueKey = getUniqueKey(req);
		if (uniqueKey == null) {
			return;
		}

		if (adService.isDeviceActivePolicySelectedFirst()) {
			this.deviceRepository.setChannelIdIfAbsent(uniqueKey, ch);
		} else {
			this.deviceRepository.setChannelId(uniqueKey, ch);
		}

	}

	/**
	 * 用于api对接方式，激活回调。 mac，imei，idfa 至少有一个存在。 得到唯一标识。和激活回调获取的顺序要一致
	 * 
	 * @param adRequest
	 * @return
	 */
	private String getUniqueKey(TrackingRequest adRequest) {
		TrackingRequest req = adRequest;
		// 顺序如下：
		// MAC(1,"mac"),
		// MAC1(2,"mac1"),
		// IMEI(3,"imei"),
		// IDFA(4,"idfa"),
		// DUID(5,"duid"),
		// ANDROIDID(6,"androidid"),
		// UDID(7,"udid"),
		// AAID(8,"aaid"),
		// COOKIE(9,"cookieid");

		if (!StringUtils.isEmpty(req.getMac())) {
			return req.getMac();
		}

		if (!StringUtils.isEmpty(req.getImei())) {
			return req.getImei();
		}

		if (!StringUtils.isEmpty(req.getIdfa())) {
			return req.getIdfa();
		}
		return null;

	}
}
